package repository

import (
	"context"

	"github.com/devops-smartbot/devops-smartbot/services/alert-service/internal/model"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

// MongoRepository implements Repository backed by MongoDB.
type MongoRepository struct {
	collection *mongo.Collection
}

// NewMongoRepository constructs a Mongo-backed repository.
func NewMongoRepository(db *mongo.Database) *MongoRepository {
	return &MongoRepository{collection: db.Collection("alerts")}
}

// ListAlerts fetches alerts with simple pagination.
func (r *MongoRepository) ListAlerts(ctx context.Context, filter Filter) ([]model.Alert, int64, error) {
	var alerts []model.Alert

	mongoFilter := bson.M{}
	if len(filter.Severity) > 0 {
		mongoFilter["severity"] = bson.M{"$in": filter.Severity}
	}
	if len(filter.Status) > 0 {
		mongoFilter["status"] = bson.M{"$in": filter.Status}
	}

	findOpts := options.Find()
	if filter.Limit > 0 {
		findOpts.SetLimit(filter.Limit)
	}
	if filter.Offset > 0 {
		findOpts.SetSkip(filter.Offset)
	}
	findOpts.SetSort(bson.M{"starts_at": -1})

	cursor, err := r.collection.Find(ctx, mongoFilter, findOpts)
	if err != nil {
		return nil, 0, err
	}
	defer cursor.Close(ctx)

	if err := cursor.All(ctx, &alerts); err != nil {
		return nil, 0, err
	}

	total, err := r.collection.CountDocuments(ctx, mongoFilter)
	if err != nil {
		return nil, 0, err
	}

	return alerts, total, nil
}

// GetAlert fetches a single alert by ID.
func (r *MongoRepository) GetAlert(ctx context.Context, id string) (*model.Alert, error) {
	var alert model.Alert
	if err := r.collection.FindOne(ctx, bson.M{"_id": id}).Decode(&alert); err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		return nil, err
	}
	return &alert, nil
}

// GetAlertByFingerprint fetches a single alert by fingerprint.
func (r *MongoRepository) GetAlertByFingerprint(ctx context.Context, fingerprint string) (*model.Alert, error) {
	var alert model.Alert
	if err := r.collection.FindOne(ctx, bson.M{"fingerprint": fingerprint}).Decode(&alert); err != nil {
		if err == mongo.ErrNoDocuments {
			return nil, nil
		}
		return nil, err
	}
	return &alert, nil
}

// CreateAlert creates a new alert.
func (r *MongoRepository) CreateAlert(ctx context.Context, alert *model.Alert) error {
	_, err := r.collection.InsertOne(ctx, alert)
	return err
}

// UpdateAlert updates an existing alert.
func (r *MongoRepository) UpdateAlert(ctx context.Context, alert *model.Alert) error {
	_, err := r.collection.ReplaceOne(ctx, bson.M{"_id": alert.ID}, alert)
	return err
}

var _ Repository = (*MongoRepository)(nil)
